package com.github.cosycode.imgtool.flow;

import com.github.cosycode.flow.base.ActionRecord;
import com.github.cosycode.flow.base.IEnumStage;
import com.github.cosycode.flow.base.JobFlowContext;
import com.github.cosycode.flow.base.JobStageRecord;
import com.github.cosycode.imgtool.action.AddressMdLinkByModifyLinkAction;
import com.github.cosycode.imgtool.action.CleanDangingPictureAction;
import com.github.cosycode.imgtool.action.MarkdownImageLinkCheckAction;
import com.github.cosycode.imgtool.action.MdDanglingLinkMatchAndFixAction;
import com.github.cosycode.imgtool.rule.CheckConfig;
import com.github.cosycode.imgtool.rule.MarkdownRepairSource;
import com.github.cosycode.imgtool.util.FileCleanUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.util.List;

/**
 * <b>Description : </b>
 * <p>
 * <b>created in </b> 2022/12/15
 * </p>
 *
 * @author pengfchen
 * @since
 **/
@Slf4j
public class TidyMarkdownProjectFlow {

    public static void main(String[] args) {
        String projectPath = "P:\\git-note\\working-note";
        String deletePath = projectPath + "\\.delete";
        CheckConfig config = new CheckConfig();

//        config.setWebPathEnable(true, false);
        config.setRelatePathEnable(true);
        config.setAbsolutePathEnable(true);
        config.setRootPathEnable(projectPath);

        TidyMarkdownProjectContext context = new TidyMarkdownProjectContext();
        context.setProjectFilePath(projectPath);
        context.setDeleteFileDir(deletePath);
        context.setConfig(config);
        context.setDryRun(false);
        context.exec(TidyMarkdownProjectEnum.CONTROLLER);
    }


    public enum TidyMarkdownProjectEnum implements IEnumStage<TidyMarkdownProjectContext> {
        /**
         * 记录执行步骤, 记录数据.
         * 全局控制.
         */
        CONTROLLER {
            @Override
            public void callAction(TidyMarkdownProjectContext context, ActionRecord<?> actionRecord) throws Exception {
            }

            @Override
            public IEnumStage<TidyMarkdownProjectContext> toNextStage(TidyMarkdownProjectContext context, JobStageRecord<?> jobStageRecord) {
                return CHECK_AND_SEE;
            }
        },
        CHECK_AND_SEE {
            @Override
            public void callAction(TidyMarkdownProjectContext context, ActionRecord<?> actionRecord) throws Exception {
                final String rootPath = context.projectFilePath;
                CheckConfig config = CheckConfig.geneConfig(true, rootPath, true);
                MarkdownImageLinkCheckAction checkAction = new MarkdownImageLinkCheckAction(config, rootPath);
                checkAction.setDryRun(context.isDryRun());
                checkAction.process((ActionRecord<MarkdownImageLinkCheckAction.MarkdownProjectImageLinkExistReport>) actionRecord);
            }

            @Override
            public IEnumStage<TidyMarkdownProjectContext> toNextStage(TidyMarkdownProjectContext context, JobStageRecord<?> jobStageRecord) {
                return MODIFY_MARKDOWN_IMG_LINK;
            }
        },
        /**
         * 根据需求修改 markdown 文件 link
         */
        MODIFY_MARKDOWN_IMG_LINK {
            @Override
            public void callAction(TidyMarkdownProjectContext context, ActionRecord<?> actionRecord) throws Exception {
                String projectFilePath = context.getProjectFilePath();
                MarkdownRepairSource source = new MarkdownRepairSource();
                source.addMarkdownFile(new File(projectFilePath));
                source.addImgFile(new File(projectFilePath));

                AddressMdLinkByModifyLinkAction addressMdLinkByModifyLinkAction = new AddressMdLinkByModifyLinkAction(source, context.getConfig());
                addressMdLinkByModifyLinkAction.setDryRun(context.isDryRun());
                addressMdLinkByModifyLinkAction.process((ActionRecord<AddressMdLinkByModifyLinkAction.MdLlMfReport>) actionRecord);
            }

            @Override
            public IEnumStage<TidyMarkdownProjectContext> toNextStage(TidyMarkdownProjectContext context, JobStageRecord<?> jobStageRecord) {
                return SUIT_LINK_BY_MOVE_PICTURE;
            }
        },
        /**
         * 1. 通过 markdown 中的 link 扫描出和 link 匹配的图片, 以及没有匹配 link 的图片, 并返回一个 reporter.
         * 2. 对没有匹配的图片进行匹配, 并生成一个匹配报告.
         * <p>
         * 0. 正常的 link 和 图片
         * 1. 匹配到图片的 link
         * 2. 未匹配到图片的 link
         * 3. 匹配到 link 的图片
         * 4. 未匹配到 link 的图片
         * </p>
         */
        SUIT_LINK_BY_MOVE_PICTURE {
            @Override
            public void callAction(TidyMarkdownProjectContext context, ActionRecord<?> actionRecord) throws Exception {
                String projectFilePath = context.getProjectFilePath();
                MarkdownRepairSource source = new MarkdownRepairSource();
                source.addMarkdownFile(new File(projectFilePath));
                source.addImgFile(new File(projectFilePath));

                MdDanglingLinkMatchAndFixAction mdDanglingLinkMatchAndFixAction = new MdDanglingLinkMatchAndFixAction(source, context.getConfig());
                mdDanglingLinkMatchAndFixAction.setDryRun(context.isDryRun());
                mdDanglingLinkMatchAndFixAction.process((ActionRecord<MdDanglingLinkMatchAndFixAction.MdLlMfReport>) actionRecord);
            }

            @Override
            public IEnumStage<TidyMarkdownProjectContext> toNextStage(TidyMarkdownProjectContext context, JobStageRecord<?> jobStageRecord) {
                MdDanglingLinkMatchAndFixAction.MdLlMfReport result = jobStageRecord.getResult(MdDanglingLinkMatchAndFixAction.MdLlMfReport.class);
                return CLEAN_DANGING_PICTURE;
            }
        },
        CLEAN_DANGING_PICTURE {
            @Override
            public void callAction(TidyMarkdownProjectContext context, ActionRecord<?> actionRecord) throws Exception {
                String projectFilePath = context.getProjectFilePath();
                String deleteFileDir = context.getDeleteFileDir();
                CleanDangingPictureAction cleanDangingPictureAction = new CleanDangingPictureAction(projectFilePath, deleteFileDir, context.getConfig());
                cleanDangingPictureAction.setDryRun(context.isDryRun());
                cleanDangingPictureAction.process((ActionRecord<String>) actionRecord);
            }

            @Override
            public IEnumStage<TidyMarkdownProjectContext> toNextStage(TidyMarkdownProjectContext context, JobStageRecord<?> jobStageRecord) {
                return DELETE_EMPTY_DIR;
            }
        }, DELETE_EMPTY_DIR {
            @Override
            public void callAction(TidyMarkdownProjectContext context, ActionRecord<?> actionRecord) throws Exception {
                String projectFilePath = context.getProjectFilePath();
                boolean dryRun = context.isDryRun();
                List<File> emptyList = FileCleanUtils.scanEmptyDirFile(new File(projectFilePath));
                if (emptyList.isEmpty()) {
                    return;
                }
                emptyList.forEach(f -> actionRecord.appendRecord("[emptyDir] => {}", f.getAbsolutePath()));
                // 对空文件夹进行处理
                if (!dryRun) {
                    emptyList.forEach(FileCleanUtils::deleteEmptyDirCascade);
                }
            }

            @Override
            public IEnumStage<TidyMarkdownProjectContext> toNextStage(TidyMarkdownProjectContext context, JobStageRecord<?> jobStageRecord) {
                return null;
            }
        };

        @Override
        public int getCode() {
            return this.ordinal();
        }
    }

    @Data
    public static class TidyMarkdownProjectContext extends JobFlowContext {

        String projectFilePath;

        String deleteFileDir;

        CheckConfig config;
    }

}
